/* eslint-disable no-shadow */
/* eslint-disable no-multi-assign */
import G6 from '@antv/g6';
import { Tsrv } from '../o-graph/config';

const MIN_ARROW_SIZE = 3;
const MIN_BORDER_SIZE = 10;
const MIN_NODE_HEIGHT = 50;

const customPolylinePath = (cfg, startPoint, endPoint): any => {
  /* 适合处理接入点在左边和上边，起始点在右边和下边 */
  const path: Array<any> = [];
  let textX: number = 0;
  let textY: number = 0;
  const spacingX: number = endPoint.x - startPoint.x;
  const spacingY: number = endPoint.y - startPoint.y;
  path.push(['M', startPoint.x, startPoint.y]); // 开始点
  const p1 = { x: 0, y: 0 };
  const p2 = { x: 0, y: 0 };
  const p3 = { x: 0, y: 0 };
  const p4 = { x: 0, y: 0 };

  const centerY = startPoint.y + spacingY / 2;
  const centerX = startPoint.x + spacingX / 2;
  if (cfg.start.y > 0) {
    // 起始点在下边
    if (cfg.end.y === 0) {
      // 接入点在左
      if (spacingX > 0) {
        if (spacingY > 0) {
          // 接入node在右下
          p1.x = startPoint.x;
          p1.y = endPoint.y;
          textX = startPoint.x;
          textY = centerY;
        } else {
          // 接入node在右上
          p1.x = startPoint.x;
          p1.y = p2.y = startPoint.y + MIN_BORDER_SIZE;
          p2.x = p3.x = centerX;
          p3.y = endPoint.y;
          textX = p2.x;
          textY = p3.y + (p2.y - p3.y) / 2;
        }
      } else {
        if (spacingY > 0) {
          // 接入node在左下
          p1.x = startPoint.x;
          p1.y = p2.y = centerY;
          p2.x = p3.x = endPoint.x - MIN_BORDER_SIZE * 2;
          p3.y = endPoint.y;
          textX = p2.x + (p1.x - p2.x) / 2;
          textY = p1.y;
        } else {
          // 接入node在左上
          p1.x = startPoint.x;
          p1.y = p2.y = startPoint.y + MIN_BORDER_SIZE;
          p2.x = p3.x = endPoint.x - MIN_BORDER_SIZE * 2;
          p3.y = endPoint.y;
          textX = p2.x + (p1.x - p2.x) / 2;
          textY = p1.y;
        }
      }
    } else {
      // 接入点在上
      if (spacingY > 0) {
        // 接入node在下
        p1.x = startPoint.x;
        p2.x = endPoint.x;
        p1.y = p2.y = centerY;
        textX = centerX;
        textY = p2.y;
      } else {
        // 接入node在上
        p1.x = startPoint.x;
        p1.y = p2.y = startPoint.y + MIN_BORDER_SIZE;
        p2.x = p3.x = centerX;
        p3.y = p4.y = endPoint.y - MIN_BORDER_SIZE * 2;
        p4.x = endPoint.x;
        textX = p2.x;
        textY = p3.y + (p2.y - p3.y) / 2;
      }
    }
  } else if (cfg.start.x > 0) {
    // 起始点在右边
    if (cfg.end.y === 0) {
      // 接入点在左
      if (spacingX > 0) {
        // 接入node在右
        p1.x = p2.x = centerX;
        p1.y = startPoint.y;
        p2.y = endPoint.y;
        textX = p1.x;
        textY = p2.y + (p1.y - p2.y) / 2;
      } else {
        if (spacingY > 0) {
          // 接入node在左下
          p1.x = p2.x = startPoint.x + MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y + MIN_NODE_HEIGHT + MIN_BORDER_SIZE;
          p3.x = p4.x = endPoint.x - MIN_BORDER_SIZE * 2;
          p4.y = endPoint.y;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        } else {
          // 接入node在左上
          p1.x = p2.x = startPoint.x + MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y - MIN_NODE_HEIGHT - MIN_BORDER_SIZE;
          p3.x = p4.x = endPoint.x - MIN_BORDER_SIZE * 2;
          p4.y = endPoint.y;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        }
      }
    } else {
      // 接入点在上
      if (spacingX > 0) {
        if (spacingY > 0) {
          // 接入node在右下
          p1.x = endPoint.x;
          p1.y = startPoint.y;
          textX = centerX;
          textY = p1.y;
        } else {
          // 接入node在右上
          p1.x = p2.x = centerX;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y - MIN_BORDER_SIZE * 2;
          p3.x = endPoint.x;
          textX = p1.x;
          textY = p2.y + (p1.y - p2.y) / 2;
        }
      } else {
        if (spacingY > 0) {
          // 接入node在左下
          p1.x = p2.x = startPoint.x + MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = centerY;
          p3.x = endPoint.x;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        } else {
          // 接入node在左下
          p1.x = p2.x = startPoint.x + MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y - MIN_BORDER_SIZE - MIN_NODE_HEIGHT;
          p3.x = endPoint.x;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        }
      }
    }
  } else if (cfg.start.x < 0) {
    // 起始点在左边
    if (cfg.end.y === 0) {
      // 接入点在左
      if (spacingX > 0) {
        // 接入node在右
        p1.x = p2.x = startPoint.x - MIN_BORDER_SIZE;
        p1.y = startPoint.y;
        p2.y = endPoint.y;
        textX = p1.x;
        textY = p1.y + (p2.y - p1.y) / 2;
      } else {
        p1.x = p2.x = endPoint.x + MIN_BORDER_SIZE * 2;
        p1.y = startPoint.y;
        p2.y = endPoint.y;
        textX = p1.x;
        textY = p1.y + (p2.y - p1.y) / 2;
      }
    } else {
      // 接入点在上
      if (spacingX > 0) {
        // 接入node在右
        if (spacingY > 0) {
          // 接入node在右下
          p1.x = p2.x = startPoint.x - MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = centerY;
          p3.x = endPoint.x;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        } else {
          // 接入node在右上
          p1.x = p2.x = startPoint.x - MIN_BORDER_SIZE;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y - MIN_BORDER_SIZE * 2;
          p3.x = endPoint.x;
          textX = p3.x + (p2.x - p3.x) / 2;
          textY = p2.y;
        }
      } else {
        if (spacingY > 0) {
          // 接入node在左下
          p1.x = endPoint.x;
          p1.y = startPoint.y;
          textX = centerX;
          textY = p1.y;
        } else {
          // 接入node在左上
          p1.x = p2.x = centerX;
          p1.y = startPoint.y;
          p2.y = p3.y = endPoint.y - MIN_BORDER_SIZE * 2;
          p3.x = endPoint.x;
          textX = p2.x;
          textY = p2.y + (p1.y - p2.y) / 2;
        }
      }
    }
  }
  path.push(['L', p1.x, p1.y]);
  if (p2.x !== 0 && p2.y !== 0) path.push(['L', p2.x, p2.y]);
  if (p3.x !== 0 && p3.y !== 0) path.push(['L', p3.x, p3.y]);
  if (p4.x !== 0 && p4.y !== 0) path.push(['L', p4.x, p4.y]);

  path.push(['L', endPoint.x, endPoint.y]); // 结束
  return { path, textX, textY };
};

const getPath = (type, cfg) => {
  let path: Array<any> = [];
  let sourceNode;
  let targetNode;
  let start;
  let end;

  if (typeof cfg.source === 'string') {
    cfg.source = cfg.sourceNode;
  }
  if (!cfg.start) {
    cfg.start = {
      x: 0,
      y: 17
    };
  }
  if (!cfg.end) {
    cfg.end = {
      x: 0,
      y: -17
    };
  }

  if (!cfg.source.x) {
    sourceNode = cfg.source.getModel();
    start = { x: sourceNode.x + cfg.start.x, y: sourceNode.y + cfg.start.y };
  } else {
    start = cfg.source;
  }

  if (typeof cfg.target === 'string') {
    cfg.target = cfg.targetNode;
  }

  if (!cfg.target.x) {
    targetNode = cfg.target.getModel();
    end = { x: targetNode.x + cfg.end.x, y: targetNode.y + cfg.end.y };
  } else {
    end = cfg.target;
  }

  switch (type) {
    case 'customPolyline':
      path = customPolylinePath(cfg, start, end);
      break;
    default:
  }
  return path;
};

const customPolyline = () => {
  return {
    draw(cfg, group) {
      const path: any = getPath('customPolyline', cfg);
      const textX = path.textX;
      const textY = path.textY;

      let lineWidth = 1;
      lineWidth = lineWidth > MIN_ARROW_SIZE ? lineWidth : MIN_ARROW_SIZE;
      const width = (lineWidth * 10) / 3;
      const halfHeight = (lineWidth * 4) / 3;
      const radius = lineWidth * 4;
      const endArrowPath = [
        ['M', width, halfHeight],
        ['L', 0, 0],
        ['L', width, -halfHeight],
        ['A', radius, radius, 0, 0, 1, width, halfHeight],
        ['Z']
      ];

      const gId = `edge${Tsrv.utils.custUUID(16, 16)}`;
      const keyShape = group.addShape('path', {
        attrs: {
          id: gId,
          stroke: '#6ab7ff',
          lineWidth: 2,
          labelX: textX,
          labelY: textY,
          endArrow: true,
          // endArrow: {
          //   path: endArrowPath
          // },
          // startArrow: {
          //   path: 'M 10,0 L -10,-10 L -10,10 Z', // 自定义箭头为中心点在(0, 0)，指向 x 轴正方向的path
          //   d: 10
          // },
          // endArrow: {
          //   path: 'M 10,0 L -10,-10 L -10,10 Z', // 自定义箭头为中心点在(0, 0)，指向 x 轴正方向的path
          //   d: 10
          // },
          // 两线端点相交时的样式
          lineJoin: 'miter', // "bevel|round|miter"
          lineAppendWidth: 10,
          path: path.path
        },
        name: 'customPolylineArrow'
      });

      group.addShape('text', {
        attrs: {
          id: `label${Tsrv.utils.custUUID(16, 16)}`,
          x: textX,
          y: textY,
          fill: '#f40',
          textAlign: 'center',
          textBaseline: 'middle',
          text: cfg.label,
          parent: gId,
          fontSize: 14,
          lineWidth: 10,
          stroke: 'white'
        }
      });
      return keyShape;
    },
    setState(name, value, item) {
      const group = item.getContainer();
      const shape = group.get('children')[0];
      const selectStyles = () => {
        shape.attr('stroke', '#ffa0a3');
        shape.attr('lineWidth', 4);
      };
      const unSelectStyles = () => {
        shape.attr('stroke', '#6ab7ff');
        shape.attr('lineWidth', 2);
      };
      const hoverStyles = () => {
        shape.attr('stroke', '#a2bdd6');
        shape.attr('lineWidth', 6);
      };

      switch (name) {
        case 'selected':
          if (!value) {
            unSelectStyles();
          } else {
            selectStyles();
          }
          break;
        case 'hover':
          if (value) {
            hoverStyles();
          } else {
            unSelectStyles();
          }
          break;
        default:
      }
    }
  };
};
const edges = [{ edgeName: 'customPolyline', edgeConfFun: customPolyline }];
const customEdge = {
  init() {
    edges.forEach(item => {
      G6.registerEdge(item.edgeName, item.edgeConfFun());
    });
  }
};

export default customEdge;
